<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>MeCab: Yet Another Japanese Dependency Structure Analyzer</title>
<link type="text/css" rel="stylesheet" href="mecab.css">
</head>
<body>
<h1>MeCab ライブラリ</h1>
<p>
MeCabはC/C++のライブラリを提供しています。また, SWIGを通して Perl/Ruby/Python から利用することも可能です。
</p>
<p>
シングルスレッド環境で単純な形態素解析を行う場合は、MeCab::Tagger クラスのみでほとんどのことが行えます。マルチスレッド環境で1つの辞書を共有しながら形態素解析を行いたい場合や、MeCabの辞書を解析中にアップデートするなど、高度な応用には MeCab::Taggerに加えて、 MeCab::Model, MeCab::Lattice クラスを使用します。
</p>
<p>
C++のAPIセットのドキュメントは<a href="doxygen/annotated.html">こちら</a>を参照ください。
CのAPIセットは<a href="doxygen/globals.html">こちら</a>を参照ください。

<h2>C++ サンプルコード</h2>
<p>シングルスレッド環境 (MeCab::Tagger)</p>
<ul>
  <li>Taggerオブジェクトを生成すると、1つの辞書オブジェクトが生成されます。
</ul>
<pre>
#include &lt;iostream&gt;
#include &lt;mecab.h&gt;

#define CHECK(eval) if (! eval) { \
   const char *e = tagger ? tagger-&gt;what() : MeCab::getTaggerError(); \
   std::cerr &lt;&lt; "Exception:" &lt;&lt; e &lt;&lt; std::endl; \
   delete tagger; \
   return -1; }

// Sample of MeCab::Tagger class.
int main (int argc, char **argv) {
  char input[1024] = "太郎は次郎が持っている本を花子に渡した。";

  MeCab::Tagger *tagger = MeCab::createTagger("");
  CHECK(tagger);

  // Gets tagged result in string format.
  const char *result = tagger-&gt;parse(input);
  CHECK(result);
  std::cout &lt;&lt; "INPUT: " &lt;&lt; input &lt;&lt; std::endl;
  std::cout &lt;&lt; "RESULT: " &lt;&lt; result &lt;&lt; std::endl;

  // Gets N best results in string format.
  result = tagger-&gt;parseNBest(3, input);
  CHECK(result);
  std::cout &lt;&lt; "NBEST: " &lt;&lt; std::endl &lt;&lt; result;

  // Gets N best results in sequence.
  CHECK(tagger-&gt;parseNBestInit(input));
  for (int i = 0; i &lt; 3; ++i) {
    std::cout &lt;&lt; i &lt;&lt; ":" &lt;&lt; std::endl &lt;&lt; tagger-&gt;next();
  }

  // Gets Node object.
  const MeCab::Node* node = tagger-&gt;parseToNode(input);
  CHECK(node);
  for (; node; node = node-&gt;next) {
    std::cout &lt;&lt; node-&gt;id &lt;&lt; ' ';
    if (node-&gt;stat == MECAB_BOS_NODE)
      std::cout &lt;&lt; "BOS";
    else if (node-&gt;stat == MECAB_EOS_NODE)
      std::cout &lt;&lt; "EOS";
    else
      std::cout.write (node-&gt;surface, node-&gt;length);

    std::cout &lt;&lt; ' ' &lt;&lt; node-&gt;feature
	      &lt;&lt; ' ' &lt;&lt; (int)(node-&gt;surface - input)
	      &lt;&lt; ' ' &lt;&lt; (int)(node-&gt;surface - input + node-&gt;length)
	      &lt;&lt; ' ' &lt;&lt; node-&gt;rcAttr
	      &lt;&lt; ' ' &lt;&lt; node-&gt;lcAttr
	      &lt;&lt; ' ' &lt;&lt; node-&gt;posid
	      &lt;&lt; ' ' &lt;&lt; (int)node-&gt;char_type
	      &lt;&lt; ' ' &lt;&lt; (int)node-&gt;stat
	      &lt;&lt; ' ' &lt;&lt; (int)node-&gt;isbest
	      &lt;&lt; ' ' &lt;&lt; node-&gt;alpha
	      &lt;&lt; ' ' &lt;&lt; node-&gt;beta
	      &lt;&lt; ' ' &lt;&lt; node-&gt;prob
	      &lt;&lt; ' ' &lt;&lt; node-&gt;cost &lt;&lt; std::endl;
  }

  // Dictionary info.
  const MeCab::DictionaryInfo *d = tagger-&gt;dictionary_info();
  for (; d; d = d-&gt;next) {
    std::cout &lt;&lt; "filename: " &lt;&lt;  d-&gt;filename &lt;&lt; std::endl;
    std::cout &lt;&lt; "charset: " &lt;&lt;  d-&gt;charset &lt;&lt; std::endl;
    std::cout &lt;&lt; "size: " &lt;&lt;  d-&gt;size &lt;&lt; std::endl;
    std::cout &lt;&lt; "type: " &lt;&lt;  d-&gt;type &lt;&lt; std::endl;
    std::cout &lt;&lt; "lsize: " &lt;&lt;  d-&gt;lsize &lt;&lt; std::endl;
    std::cout &lt;&lt; "rsize: " &lt;&lt;  d-&gt;rsize &lt;&lt; std::endl;
    std::cout &lt;&lt; "version: " &lt;&lt;  d-&gt;version &lt;&lt; std::endl;
  }

  delete tagger;

  return 0;
}

</pre>

<h2>C++ サンプルコード</h2>
<p>マルチスレッド環境 (MeCab::Tagger, MeCab::Model, MeCab::Lattice)</p>
<ul>
<li>MeCab::createModel() を使い、Modelオブジェクトを生成します
<li>model->createTagger() を使い、Taggerオブジェクトを生成します。Taggerはスレッド毎に複数作成しても、同一のmodelを共有します。Taggerがアクティブの間は、modelを削除してはなりません。
<li>model->createLattice もしくは MeCab::createLattice() を使い、Latticeオブジェクトを作成します。Latticeオプジェクトは解析に必要なすべてのローカル変数を含んでいます。必ずスレッド毎に1つのオブジェクトを作成してください
<li>model->swap(antoher_model) を呼ぶと、model から生成されたすべてのTaggerオブジェクトのモデルを another_modelに置き換えます。この操作はスレッドセーフです。
</ul>
<pre>
#include &lt;iostream&gt;
#include &lt;mecab.h&gt;

#define CHECK(eval) if (! eval) { \
   const char *e = tagger ? tagger-&gt;what() : MeCab::getTaggerError(); \
   std::cerr &lt;&lt; "Exception:" &lt;&lt; e &lt;&lt; std::endl; \
   delete tagger; \
   return -1; }

int main (int argc, char **argv) {
  char input[1024] = "太郎は次郎が持っている本を花子に渡した。";

  // Create model object.
  MeCab::Model *model = MeCab::createModel(argc, argv);

  // Create Tagger
  // All taggers generated by Model::createTagger() method share
  // the same model/dictoinary.
  MeCab::Tagger *tagger = model-&gt;createTagger();
  CHECK(tagger);

  // Create lattice object per thread.
  MeCab::Lattice *lattice = model-&gt;createLattice();

  // Gets tagged result in string
  lattice-&gt;set_sentence(input);

  // this method is thread safe, as long as |lattice| is thread local.
  CHECK(tagger-&gt;parse(lattice));
  std::cout &lt;&lt; lattice-&gt;toString() &lt;&lt; std::endl;

  // Gets node object.
  const MeCab::Node* node = lattice-&gt;bos_node();
  CHECK(node);
  for (; node; node = node-&gt;next) {
    std::cout &lt;&lt; node-&gt;id &lt;&lt; ' ';
    if (node-&gt;stat == MECAB_BOS_NODE)
      std::cout &lt;&lt; "BOS";
    else if (node-&gt;stat == MECAB_EOS_NODE)
      std::cout &lt;&lt; "EOS";
    else
      std::cout.write (node-&gt;surface, node-&gt;length);

    std::cout &lt;&lt; ' ' &lt;&lt; node-&gt;feature
	      &lt;&lt; ' ' &lt;&lt; (int)(node-&gt;surface - input)
	      &lt;&lt; ' ' &lt;&lt; (int)(node-&gt;surface - input + node-&gt;length)
	      &lt;&lt; ' ' &lt;&lt; node-&gt;rcAttr
	      &lt;&lt; ' ' &lt;&lt; node-&gt;lcAttr
	      &lt;&lt; ' ' &lt;&lt; node-&gt;posid
	      &lt;&lt; ' ' &lt;&lt; (int)node-&gt;char_type
	      &lt;&lt; ' ' &lt;&lt; (int)node-&gt;stat
	      &lt;&lt; ' ' &lt;&lt; (int)node-&gt;isbest
	      &lt;&lt; ' ' &lt;&lt; node-&gt;alpha
	      &lt;&lt; ' ' &lt;&lt; node-&gt;beta
	      &lt;&lt; ' ' &lt;&lt; node-&gt;prob
	      &lt;&lt; ' ' &lt;&lt; node-&gt;cost &lt;&lt; std::endl;
  }


  // begin_nodes/end_nodes
  const size_t len = lattice-&gt;size();
  for (int i = 0; i &lt;= len; ++i) {
    MeCab::Node *b = lattice-&gt;begin_nodes(i);
    MeCab::Node *e = lattice-&gt;end_nodes(i);
    for (; b; b = b-&gt;bnext) {
      printf("B[%d] %s\t%s\n", i, b-&gt;surface, b-&gt;feature);
    }
    for (; e; e = e-&gt;enext) {
      printf("E[%d] %s\t%s\n", i, e-&gt;surface, e-&gt;feature);
    }
  }

  // N best results
  lattice-&gt;set_request_type(MECAB_NBEST);
  lattice-&gt;set_sentence(input);
  CHECK(tagger-&gt;parse(lattice));
  for (int i = 0; i &lt; 10; ++i) {
    std::cout &lt;&lt; "NBEST: " &lt;&lt; i &lt;&lt; std::endl;
    std::cout &lt;&lt; lattice-&gt;toString();
    if (!lattice-&gt;next()) {
      // No more results
      break;
    }
  }

  // Marginal probabilities
  lattice-&gt;remove_request_type(MECAB_NBEST);
  lattice-&gt;set_request_type(MECAB_MARGINAL_PROB);
  lattice-&gt;set_sentence(input);
  CHECK(tagger-&gt;parse(lattice));
  std::cout &lt;&lt; lattice-&gt;theta() &lt;&lt; std::endl;
  for (const MeCab::Node *node = lattice-&gt;bos_node();
       node; node = node-&gt;next) {
    std::cout.write(node-&gt;surface, node-&gt;length);
    std::cout &lt;&lt; "\t" &lt;&lt; node-&gt;feature;
    std::cout &lt;&lt; "\t" &lt;&lt; node-&gt;prob &lt;&lt; std::endl;
  }

  // Dictionary info
  const MeCab::DictionaryInfo *d = model-&gt;dictionary_info();
  for (; d; d = d-&gt;next) {
    std::cout &lt;&lt; "filename: " &lt;&lt;  d-&gt;filename &lt;&lt; std::endl;
    std::cout &lt;&lt; "charset: " &lt;&lt;  d-&gt;charset &lt;&lt; std::endl;
    std::cout &lt;&lt; "size: " &lt;&lt;  d-&gt;size &lt;&lt; std::endl;
    std::cout &lt;&lt; "type: " &lt;&lt;  d-&gt;type &lt;&lt; std::endl;
    std::cout &lt;&lt; "lsize: " &lt;&lt;  d-&gt;lsize &lt;&lt; std::endl;
    std::cout &lt;&lt; "rsize: " &lt;&lt;  d-&gt;rsize &lt;&lt; std::endl;
    std::cout &lt;&lt; "version: " &lt;&lt;  d-&gt;version &lt;&lt; std::endl;
  }

  // Swap model atomically.
  MeCab::Model *another_model = MeCab::createModel("");
  model-&gt;swap(another_model);

  delete lattice;
  delete tagger;
  delete model;

  return 0;
}

</pre>

<h2>C サンプルコード</h2>
シングルスレッド環境
<pre>
#include &lt;mecab.h&gt;
#include &lt;stdio.h&gt;

#define CHECK(eval) if (! eval) { \
    fprintf (stderr, "Exception:%s\n", mecab_strerror (mecab)); \
    mecab_destroy(mecab); \
    return -1; }

int main (int argc, char **argv)  {
  char input[] = "太郎は次郎が持っている本を花子に渡した。";
  mecab_t *mecab;
  const mecab_node_t *node;
  const char *result;
  int i;
  size_t len;

  // Create tagger object
  mecab = mecab_new(argc, argv);
  CHECK(mecab);

  // Gets tagged result in string.
  result = mecab_sparse_tostr(mecab, input);
  CHECK(result)
  printf ("INPUT: %s\n", input);
  printf ("RESULT:\n%s", result);

  // Gets N best results
  result = mecab_nbest_sparse_tostr (mecab, 3, input);
  CHECK(result);
  fprintf (stdout, "NBEST:\n%s", result);

  CHECK(mecab_nbest_init(mecab, input));
  for (i = 0; i < 3; ++i) {
    printf ("%d:\n%s", i, mecab_nbest_next_tostr (mecab));
  }

  // Gets node object
  node = mecab_sparse_tonode(mecab, input);
  CHECK(node);
  for (; node; node = node-&gt;next) {
    if (node-&gt;stat == MECAB_NOR_NODE || node-&gt;stat == MECAB_UNK_NODE) {
      fwrite (node-&gt;surface, sizeof(char), node-&gt;length, stdout);
      printf("\t%s\n", node-&gt;feature);
    }
  }

  // Dictionary info
  const mecab_dictionary_info_t *d = mecab_dictionary_info(mecab);
  for (; d; d = d-&gt;next) {
    printf("filename: %s\n", d-&gt;filename);
    printf("charset: %s\n", d-&gt;charset);
    printf("size: %d\n", d-&gt;size);
    printf("type: %d\n", d-&gt;type);
    printf("lsize: %d\n", d-&gt;lsize);
    printf("rsize: %d\n", d-&gt;rsize);
    printf("version: %d\n", d-&gt;version);
  }

  mecab_destroy(mecab);

  return 0;
}

</pre>

<h2>C サンプルコード</h2>
マルチスレッド環境
<pre>
#include &lt;mecab.h&gt;
#include &lt;stdio.h&gt;

#define CHECK(eval) if (! eval) { \
    fprintf (stderr, "Exception:%s\n", mecab_strerror (mecab)); \
    mecab_destroy(mecab); \
    return -1; }

int main (int argc, char **argv)  {
  char input[] = "太郎は次郎が持っている本を花子に渡した。";
  mecab_model_t *model, *another_model;
  mecab_t *mecab;
  mecab_lattice_t *lattice;
  const mecab_node_t *node;
  const char *result;
  int i;
  size_t len;

  model = mecab_model_new(argc, argv);
  CHECK(model);

  mecab = mecab_model_new_tagger(model);
  CHECK(mecab);

  lattice = mecab_model_new_lattice(model);
  CHECK(lattice);

  mecab_lattice_set_sentence(lattice, input);
  mecab_parse_lattice(mecab, lattice);

  printf("RESULT: %s\n", mecab_lattice_tostr(lattice));

  node = mecab_lattice_get_bos_node(lattice);
  for (;  node; node = node-&gt;next) {
    printf("%d ", node-&gt;id);

    if (node-&gt;stat == MECAB_BOS_NODE)
      printf("BOS");
    else if (node-&gt;stat == MECAB_EOS_NODE)
      printf("EOS");
    else
      fwrite (node-&gt;surface, sizeof(char), node-&gt;length, stdout);

    printf(" %s %d %d %d %d %d %d %d %d %f %f %f %ld\n",
	   node-&gt;feature,
	   (int)(node-&gt;surface - input),
	   (int)(node-&gt;surface - input + node-&gt;length),
	   node-&gt;rcAttr,
	   node-&gt;lcAttr,
	   node-&gt;posid,
	   (int)node-&gt;char_type,
	   (int)node-&gt;stat,
	   (int)node-&gt;isbest,
	   node-&gt;alpha,
	   node-&gt;beta,
	   node-&gt;prob,
	   node-&gt;cost);
  }

  len = mecab_lattice_get_size(lattice);
  for (i = 0; i &lt;= len; ++i) {
    mecab_node_t *b, *e;
    b = mecab_lattice_get_begin_nodes(lattice, (size_t)i);
    e = mecab_lattice_get_end_nodes(lattice, (size_t)i);
    for (; b; b = b-&gt;bnext) {
        printf("B[%d] %s\t%s\n", i, b-&gt;surface, b-&gt;feature);
    }
    for (; e; e = e-&gt;enext) {
        printf("E[%d] %s\t%s\n", i, e-&gt;surface, e-&gt;feature);
    }
  }

  mecab_lattice_set_sentence(lattice, input);
  mecab_lattice_set_request_type(lattice, MECAB_NBEST);
  mecab_parse_lattice(mecab, lattice);
  for (i = 0; i &lt; 10; ++i) {
    fprintf(stdout, "%s", mecab_lattice_tostr(lattice));
    if (!mecab_lattice_next(lattice)) {
      break;
    }
  }

  mecab_lattice_set_sentence(lattice, input);
  mecab_lattice_set_request_type(lattice, MECAB_MARGINAL_PROB);
  mecab_lattice_set_theta(lattice, 0.001);
  mecab_parse_lattice(mecab, lattice);
  node = mecab_lattice_get_bos_node(lattice);
  for (;  node; node = node-&gt;next) {
    fwrite(node-&gt;surface, sizeof(char), node-&gt;length, stdout);
    fprintf(stdout, "\t%s\t%f\n", node-&gt;feature, node-&gt;prob);
  }

  mecab_set_lattice_level(mecab, 0);
  mecab_set_all_morphs(mecab, 1);
  node = mecab_sparse_tonode(mecab, input);
  CHECK(node);
  for (; node; node = node-&gt;next) {
    fwrite (node-&gt;surface, sizeof(char), node-&gt;length, stdout);
    printf("\t%s\n", node-&gt;feature);
  }

  const mecab_dictionary_info_t *d = mecab_dictionary_info(mecab);
  for (; d; d = d-&gt;next) {
    printf("filename: %s\n", d-&gt;filename);
    printf("charset: %s\n", d-&gt;charset);
    printf("size: %d\n", d-&gt;size);
    printf("type: %d\n", d-&gt;type);
    printf("lsize: %d\n", d-&gt;lsize);
    printf("rsize: %d\n", d-&gt;rsize);
    printf("version: %d\n", d-&gt;version);
  }


  mecab_destroy(mecab);
  mecab_lattice_destroy(lattice);
  mecab_model_destory(model);

  return 0;
}

</pre>

<h2><a name="compile">コンパイル方法</a></h2>

<ul>
<li>UNIX の場合 </li>

<pre>
% cc -O2 `mecab-config --cflags` example.c -o example \
         `mecab-config --libs`
</pre>

<li>Windows の場合 </li>
<p>まず, コンパイル作業を行うディレクトリに include\mecab.h,
bin\libmecab.dll lib\libmecab.lib をコピーします.
この後の作業は, 使用するコンパイラによって微妙に変わります.</p>

<ul>
<li>cygwin/mingw 環境の場合</li>
<pre>
% gcc -DDLL_IMPORT -I. example.c -o example.exe libmecab.dll
</pre>

<li>VC++ 環境の場合</li>
<pre>
% cl -DDLL_IMPORT -I. example.c libmecab.lib
</pre>
</ul>
</ul>
<hr>
</body>
</html>

